#!/usr/bin/env python
# coding=utf-8

import xlrd
import os
import sys
import google
import re

from google.protobuf.descriptor import FieldDescriptor

sys.path.append("./clientproto")

#import table_common_pb2

curr_row = 0
FIELD_INDEX_NAME = 0
FIELD_INDEX_NUMBER = 1
FIELD_INDEX_TYPE = 2
FIELD_INDEX_LABEL = 3
FIELD_INDEX_OPTION = 4


readed_protos_desc = {}
readed_tables = {}
def ParseTableLinked(field_option, row_value):

    value_index = 0
    field_type = None
    field_value = None
    field_label = None
    
    if field_option not in readed_protos_desc:
        key_index = 0
        list = field_option.split('#')
        table_name = list[0]
        key_name = list[1]
        value_name = list[2]
        pb2 = str(table_name).lower() + "_pb2"
        module = __import__(pb2)
        proto_desc = get_proto_desc(module, str(table_name ).upper())

        for field_desc in proto_desc:
            if field_desc[FIELD_INDEX_NAME] == key_name:
                key_index = field_desc[FIELD_INDEX_NUMBER] - 1
            elif field_desc[FIELD_INDEX_NAME] == value_name:
                value_index = field_desc[FIELD_INDEX_NUMBER] - 1
                field_type = field_desc[FIELD_INDEX_TYPE]
                field_label = field_desc[FIELD_INDEX_LABEL]
                break
        readed_protos_desc[field_option] = (value_index, field_type, field_label)
        readed_tables[field_option] = read_excel(table_name, key_index)
    
    value_index, field_type, field_label = readed_protos_desc[field_option]
    table = readed_tables[field_option]
    field_value = table[int(row_value)][value_index]
    
    return field_type, field_value, field_label

def read_excel(excel_name, key_index):
    table = {}
    key_index = 0
    excel_file = './workbook/' + excel_name + '.xlsx'
    readed_tables[excel_name] = xlrd.open_workbook(excel_file)
    sheet = readed_tables[excel_name].sheet_by_index(0)

    for rows_read in range(4, sheet.nrows):
        row_data = sheet.row_values(rows_read)
        table[int(row_data[key_index])] = row_data
    return table
    

##### main process #####
def Process(excel_Name, table_head):
    if table_head == None:
        excel_file = './workbook/' + excel_Name + '.xlsx'
    else:
        excel_file = './workbook/' + table_head + excel_Name + '.xlsx'
    entry_name = str(excel_Name).upper()
    entry_list_name = entry_name + 'ARRAY'

    tbl_file = str(excel_Name).lower() + ".bytes"

    pb2 = str(excel_Name).lower() + "_pb2"
    module = __import__(pb2)
    
    proto_desc = get_proto_desc(module, entry_name)
    
    book = xlrd.open_workbook(excel_file)
    sheet = book.sheet_by_index(0)
    row_array = getattr(module, entry_list_name)()

    global curr_row
    for curr_row in range(4,sheet.nrows):
        row_values = sheet.row_values(curr_row)
        row = row_array.rows.add()
        for field_desc in proto_desc:
            row_value: str = row_values[field_desc[FIELD_INDEX_NUMBER] - 1]
            parse_field_type(row, field_desc[FIELD_INDEX_NAME], field_desc[FIELD_INDEX_TYPE], field_desc[FIELD_INDEX_LABEL], field_desc[FIELD_INDEX_OPTION], row_value)
    
    f = open(tbl_file, 'wb')
    f.write(row_array.SerializeToString())
    f.close()
    
def get_proto_desc(module, entry_name):
    proto_desc = []
    for desc in getattr(module, '_' + entry_name).fields:
        if desc.number > 256:
            continue
        field_name = desc.name

        if field_name[0] == '_':
            continue
        field_number = desc.number
        field_label = desc.label
        field_type = None  
        field_option = None
        if desc.has_options:
            field_option = desc.GetOptions()
   
        if desc.type == desc.TYPE_INT32 or \
                desc.type == desc.TYPE_INT64 or \
                desc.type == desc.TYPE_SINT32 or \
                desc.type == desc.TYPE_SINT64 or \
                desc.type == desc.TYPE_FIXED32 or \
                desc.type == desc.TYPE_FIXED64 or \
                desc.type == desc.TYPE_UINT32 or \
                desc.type == desc.TYPE_UINT64 or \
                desc.type == desc.TYPE_ENUM:
            field_type = int
        elif desc.type == desc.TYPE_BOOL:
            field_type = bool
        elif desc.type == desc.TYPE_FLOAT:
            field_type = float
        elif desc.type == desc.TYPE_BYTES or \
                desc.type == desc.TYPE_STRING:
            field_type = str
        else:
            print('不支持的类型')
        proto_desc += [(field_name, field_number, field_type, field_label, field_option)]
    return proto_desc


def parse_field_type(row, field_name, field_type, field_label, field_option, row_value):
    #表格中禁用浮点类型，但是Excel中会产生X.9999999情况，需要特殊处理
    if row_value != "" and type(row_value) == float:
        v = int(row_value)
        if str(row_value).find(".99") > -1:
            v += 1
        row_value = str(v)
    if field_type == str:  # str 类型
        if field_label == FieldDescriptor.LABEL_REPEATED:
            v= str(row_value).strip().split('&')#replace('&','#').
            for section in v:
                if section.strip():
                    getattr(row, field_name).append(section.strip())
        else:
            setattr(row, field_name, str(row_value).replace('\\n', '\r\n'))
    elif field_type == int:  # int 类型
        if field_label == FieldDescriptor.LABEL_REPEATED:
            v = str(row_value).strip(). \
                replace('|', '^') \
                .replace('/', '^') \
                .replace('#', '^') \
                .replace('&', '^') \
                .replace(':', '^') \
                .replace('_', '^') \
                .split('^')
            for section in v:
                if section.strip():
                    getattr(row, field_name).append(int(section.strip()))
        else:
            if row_value == '':
                row_value = '0'
            # row_value = int(0) if row_value == '' else int(row_value)
            setattr(row, field_name, int(row_value))
    elif field_type == bool:  # bool 类型
        if row_value == '':
            row_value = 0
        # row_value = int(0) if row_value == '' else int(row_value)
        setattr(row, field_name, bool(row_value))
    elif field_type == float:
        if row_value == '':
            row_value = float(0)
            # else float(row_value)
        setattr(row, field_name, float(row_value))
        # µôÂä
    else:
        print("错误数据：" + str(curr_row))

if __name__ == "__main__":
    table_name = None
    table_head = None
    for arg in sys.argv[1:]:
        if table_name is None:
            table_name = arg
        elif table_head is None:
            table_head = arg
    # try:
    Process(table_name, table_head)
    # Process("box_fan", None)
    # except BaseException as e:
    # print("打包错误")
    # exit(1)
    exit(0)
